package com.yeziji.common.business.system.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.yeziji.common.IServiceImpl;
import com.yeziji.common.business.system.constant.enums.SystemPermissionTypeEnum;
import com.yeziji.common.business.system.entity.SystemPermissionEntity;
import com.yeziji.common.business.system.mapper.SystemPermissionMapper;
import com.yeziji.common.business.system.service.SystemPermissionService;
import com.yeziji.utils.expansion.Lists2;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;

/**
 * 系统权限表 服务层实现。
 *
 * @author system
 * @since 2024-12-11
 */
@Service
public class SystemPermissionServiceImpl extends IServiceImpl<SystemPermissionMapper, SystemPermissionEntity> implements SystemPermissionService {
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveBatch(Collection<SystemPermissionEntity> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return true;
        }
        Map<Integer, List<SystemPermissionEntity>> keyPermissionGroupMap = Lists2.streamToGroupBy(entities, SystemPermissionEntity::getType);
        Set<Map.Entry<Integer, List<SystemPermissionEntity>>> entries = keyPermissionGroupMap.entrySet();
        for (Map.Entry<Integer, List<SystemPermissionEntity>> entry : entries) {
            Integer type = entry.getKey();
            boolean frontSource = SystemPermissionTypeEnum.isFrontSource(type);
            boolean backedSource = SystemPermissionTypeEnum.isBackedSource(type);
            // 区分前后端资源，如果都不是就跳过
            if (!frontSource && !backedSource) {
                continue;
            }

            // 保存新的权限
            List<SystemPermissionEntity> newPermissions = entry.getValue();
            // 后端资源除了 key 不能重复之外，name 也不能重复
            if (backedSource) {
                this.switchComparatorSaveBatch(type, newPermissions, SystemPermissionEntity::getName);
            }
            // 前端资源相同的 type 中 key 必须唯一
            else {
                this.switchComparatorSaveBatch(type, newPermissions, SystemPermissionEntity::getKey);
            }
        }

        return true;
    }

    @Override
    public Set<String> listAsPathOfParams() {
        Set<String> result = new HashSet<>();
        List<SystemPermissionEntity> list = list();
        for (SystemPermissionEntity systemPermission : list) {
            String params = systemPermission.getParams();
            if (StrUtil.isBlank(params) || (JSONUtil.isTypeJSON(params) && !params.contains("/"))) {
                continue;
            }
            result.add(params);
        }
        return result;
    }

    /**
     * 选择对比并进行批量保存
     * <p>对比存在则不操作，只保存不存在的對比数据</p>
     * @param type 对比类型
     * @param newPermissions 要新增的权限
     * @param function 对比函数
     * @param <T> 任意泛型
     */
    private <T> void switchComparatorSaveBatch(Integer type,
                                               List<SystemPermissionEntity> newPermissions,
                                               Function<SystemPermissionEntity, T> function) {
        if (Lists2.isEmpty(newPermissions)) {
            return;
        }

        List<SystemPermissionEntity> dbPermissions =
                this.queryChain()
                        .in(SystemPermissionEntity::getKey, Lists2.transformSet(newPermissions, function))
                        .eq(SystemPermissionEntity::getType, type)
                        .list();
        if (Lists2.isEmpty(dbPermissions)) {
            this.saveBatch(newPermissions, DEFAULT_BATCH_SIZE);
        } else {
            // 过滤掉数据库已存在的数据
            Map<T, SystemPermissionEntity> permissionNameMap = Lists2.streamToMap(dbPermissions, function);
            for (int i = 0; i < newPermissions.size(); i++) {
                T data = Optional.ofNullable(newPermissions.get(i)).map(function).orElse(null);
                if (data == null) {
                    continue;
                }
                SystemPermissionEntity dbPermission = permissionNameMap.get(data);
                if (dbPermission != null) {
                    newPermissions.remove(i--);
                }
            }
            if (!newPermissions.isEmpty()) {
                this.saveBatch(newPermissions, DEFAULT_BATCH_SIZE);
            }
        }
    }
}
